package com.codefish.codefishseckill.utils;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import java.util.Random;

/**
 * 密码MD5加密工具类
 *
 * @author codefish
 * @version 1.0
 * @date 2022/07/05 下午 01:24
 */
@Slf4j
public class MD5PasswordUtil {
    /**
     * 盐值
     */
    private static final String SALT = "0codefish1project";

    /**
     * 第一次加密，盐值存储在服务端中，即使数据库泄露依旧需要取猜测服务端的盐值
     *
     * @param formPassword 明文密码
     * @return 第一次加密后的密码
     */
    public static String formPasswordToSecretPassword(String formPassword) {
        StringBuilder sb = new StringBuilder();
        String str = sb.append(SALT.charAt(2))
                .append(SALT.charAt(5))
                .append(formPassword)
                .append(SALT.charAt(7))
                .append(SALT.charAt(10))
                .toString();
        return DigestUtils.md5Hex(str);
    }

    /**
     * 第二次加密密码，盐值随机生成并被存入数据库
     *
     * @param secretPassword 第一次加密后的密码
     * @param dbSalt         生成的盐值
     * @return 第二次加密后的密码
     */
    public static String secretPasswordToDBPassword(String secretPassword, String dbSalt) {
        StringBuilder sb = new StringBuilder();
        int divPos = dbSalt.length() / 2;
        String lsalt = dbSalt.substring(0, divPos);
        String rsalt = dbSalt.substring(divPos);
        String str = sb.append(lsalt)
                .append(secretPassword)
                .append(rsalt)
                .toString();
        return DigestUtils.md5Hex(str);

    }

    /**
     * 密码加密，对客户代码暴露
     *
     * @param password 前端加密后的密码
     * @param dbSalt   盐值
     * @return 两次加密后的字符串
     */
    public static String encodePassword(String password, String dbSalt, boolean doubleEncoded) {
        if (doubleEncoded) {
            password = formPasswordToSecretPassword(password);
        }
        return secretPasswordToDBPassword(password, dbSalt);
    }


    /**
     * 随机生成指定长度的盐值
     *
     * @param length 盐值长度
     * @return 盐值
     */
    public static String randSalt(int length) {
        final String str = "abcdefghijklmnopqrstuvwxyz1234567890";
        Random r = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(str.charAt(r.nextInt(str.length())));
        }
        return sb.toString();
    }

    /**
     * 登录时校验密码
     *
     * @param password       前端传入的密码
     * @param secretPassword 数据库的密码
     * @param dbSalt         数据库的盐值
     * @return 校验结果
     */
    public static boolean verifyPassword(String password, String secretPassword, String dbSalt, boolean doubleEncoded) {
        String str = encodePassword(password, dbSalt, doubleEncoded);
        return str.equals(secretPassword);
    }

    /**
     * 拼接密码和盐
     * @param secretPassword 密码
     * @param salt salt
     * @return 拼接后的字符串
     */
    public static String concatPasswordAndSalt(String secretPassword, String salt) {
        return secretPassword + ":" + salt;
    }

    /**
     * 从字符串解析密码和盐值
     *
     * @param str 给定的字符串
     * @return 返回密码和盐值 (str[0] 为密码 ，str[1] 为盐值 )，如果盐值不存在则salt值为""
     */
    public static String[] getPasswordAndSalt(String str) {
        String[] strs = str.split(":");
        if (strs.length == 1) {
            log.debug("no salt,use default salt： \"\"");
            String[] tmp = new String[2];
            tmp[0] = strs[0];
            tmp[1] = "";
            strs = tmp;
        }
        return strs;
    }


}
